package com.zxt.smartplatform.service.impl;

import com.zxt.smartplatform.cache.CategoryCache;
import com.zxt.smartplatform.events.CategoryChangeEvent;
import com.zxt.smartplatform.exceptions.AddDataException;
import com.zxt.smartplatform.exceptions.DeleteDataException;
import com.zxt.smartplatform.exceptions.QueryDataException;
import com.zxt.smartplatform.exceptions.ResultCode;
import com.zxt.smartplatform.mapper.CategoryMapper;
import com.zxt.smartplatform.pojo.Category;
import com.zxt.smartplatform.pojo.CheckType;
import com.zxt.smartplatform.pojo.User;
import com.zxt.smartplatform.service.CategoryService;
import com.zxt.smartplatform.util.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
@Transactional
public class CategoryServiceImpl implements CategoryService {

    private ApplicationContext context;

    @Autowired
    public void setContext(ApplicationContext context) {
        this.context = context;
    }

    private CategoryMapper categoryMapper;

    private CategoryCache categoryCache;

    @Autowired
    public void setCategoryCache(CategoryCache categoryCache) {
        this.categoryCache = categoryCache;
    }

    @Autowired
    public void setCategoryMapper(CategoryMapper categoryMapper) {
        this.categoryMapper = categoryMapper;
    }

    @Override
    public void addCategory(Category category) {

        Assert.isTrue(!category.isEmpty(CheckType.ADD),()->{
            throw new AddDataException("必须传递的数据不完整,请检查", ResultCode.DATA_NULL);
        });
        //这个分类如果存在了怎么办
        Category currentCategory = categoryMapper.selectByName(category.getCategoryName());

        Assert.isNull(currentCategory,()->{
            throw new AddDataException("分类已经存在", ResultCode.DATA_ALREADY_EXIST);
        });
        //设置创建的时间,当前时间
        category.setCreateTime(new Date());

       /*
        //谁创建的,应该是当前登录的用户
        //如何获取到当前登录的用户
        //如何xxxx 怎么知道,这样的问题代表着一定有一个地方的数据保存了我们想要的东西
        //我们经过分析发现数据保存到了session中,需要从session中获取
        //怎么拿到session
        //TODO session不能通过当前方法的参数传递,会导致接口污染(这个业务本身的数据和你传递的另外一个数据没有关系)
        //如何获取到session, session可以通过request获取, request在哪?

        */


        User user = SecurityUtils.getUser();
        category.setCreateBy(user.getUsername());
        categoryMapper.addCategory(category);
        //发送了一个事件 说明当前这个事情发生了
        context.publishEvent(new CategoryChangeEvent());
        //解耦,可以将核心业务代码和非核心业务代码进行剥离
    }

    @Override
    public int updateCategory(Category category) {
        return 0;
    }

    @Override
    public Category selectById(Long cId) {
        Assert.isTrue(cId>0,()->{
            throw new QueryDataException("主键超出允许的范围", ResultCode.ID_NOT_ALLOWED);
        });

        Category category = categoryCache.getValue(cId);
        return category;
    }

    @Override
    public List<Category> selectAllCategories() {
        //List<Category> categoryList = categoryMapper.selectAllEnableCategories();
        // 我们发现分类的数据是不怎么变化的,我们每次都查询数据库得到的结果都是一样的,那么就没必要查询数据库
        //按照之前的套路,我们可以把数据放到缓存中
        List<Category> categoryList = categoryCache.getAllData();
        return categoryList;
    }

    @Override
    public List<Category> selectCategoriesByNameLike(String cName) {
        Assert.hasText(cName,()->{
            throw new QueryDataException("分类名为空", ResultCode.QUERY_PARAM_EMPTY);
        });

        List<Category> categoryList = categoryCache.getAllData();
        //遍历所有的数据,如果当前分类的名字中包含我们的查询条件,则就是我们需要的数据
        List<Category> list = categoryList.stream().filter(category -> category.getCategoryName().contains(cName))
                .collect(Collectors.toList());
        return list;
    }

    @Override
    public int deleteCategoriesByIds(List<Long> ids) {
        Assert.notEmpty(ids,()->{
            throw new DeleteDataException("没有传递id", ResultCode.ID_NULL);
        });
        int result = categoryMapper.deleteCategoriesByIds(ids);
        //发布事件更新缓存
        context.publishEvent(new CategoryChangeEvent());
        return result;
    }
}